package com.dmgis.hndz.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aspose.slides.Collections.Specialized.CollectionsUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.dmgis.hndz.common.utils.*;
import com.dmgis.hndz.mapper.*;
import com.dmgis.hndz.pojo.*;
import com.dmgis.hndz.pojoVo.DisasterTypeNumVo;
import com.dmgis.hndz.pojoVo.DisasterVo;
import com.dmgis.hndz.sddz.service.Zdda01aService;
import com.dmgis.hndz.sddz.vo.LayerRcoDto1;
import com.dmgis.hndz.service.DqyjService;
import com.dmgis.hndz.service.YjfxdzYzService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.ini4j.Ini;
import org.ini4j.Wini;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageSz;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Service
public class DqyjServiceImpl implements DqyjService {

    @Value("${dmgis.ip}")
    private String dmgisIp;

    @Value("${dmgis.port}")
    private String dmgisPort;

    @Value("${dmgis.serveName}")
    private String serveName;

    @Value("${nginx.url}")
    private String nginxUrl;

    @Value("${nginx.filepath}")
    private String nginxFilepath;

    @Autowired
    private YjfxdzYzService yjfxdzYzService;

    @Autowired
    private Ybba02bMapper ybba02bMapper;

    @Autowired
    private Ybba02aMapper ybba02aMapper;

    @Autowired
    private Ybba01aMapper ybba01aMapper;

    @Autowired
    private Ybba01bMapper ybba01bMapper;

    @Autowired
    private Ybba01cMapper ybba01cMapper;

    @Autowired
    private Ybba02cMapper ybba02cMapper;

    @Autowired
    private Zdda01aService zdda01aService;

    @Override
    public List getArea() throws IOException {
        ApplicationHome applicationHome = new ApplicationHome(this.getClass());
        String filePath = applicationHome.getDir().getParentFile()
                .getParentFile().getAbsolutePath() + "file";
        String fileName = "230718095334.txt";
        File file = new File(filePath, fileName);
        String jsonStr = FileUtil.readLine(file);

        ObjectMapper objectMapper = new ObjectMapper();
        List list = objectMapper.readValue(file, List.class);
        for (Object o : list) {
            JSONObject json = new JSONObject((Map<String, Object>) o);
            AreaDto area = JSON.parseObject(json.toJSONString(), AreaDto.class);

        }
        return list;
    }

    @Override
    public List<SurfaceDto> getArea1() throws IOException {

        ApplicationHome applicationHome = new ApplicationHome(this.getClass());
        String filePath = applicationHome.getDir().getParentFile()
                .getParentFile().getAbsolutePath() + "file";
        String fileName = "230719111309.json";
        File file = new File(filePath, fileName);

        ObjectMapper objectMapper = new ObjectMapper();
        AreaDto area = objectMapper.readValue(file, AreaDto.class);
        String surfaceStr = area.getPos();
        String[] surfaceStrList = surfaceStr.split("\\*");
        List<SurfaceDto> surfaceDtoList = new ArrayList<>();
        for (String surface : surfaceStrList) {
            SurfaceDto surfaceDto = new SurfaceDto();
            String[] surfaceField = surface.split("#");
            surfaceDto.setIndex(Integer.parseInt(surfaceField[2]));
            surfaceDto.setColor("#" + Integer.toHexString(Integer.parseInt(surfaceField[0])));
            String[] points = surfaceField[1].split(",");
            double[][] range = new double[points.length][2];
            for (int i = 0; i < points.length; i++) {
                String[] point = points[i].split(" ");
                range[i][0] = Double.parseDouble(point[0]);
                range[i][1] = Double.parseDouble(point[1]);
            }
            surfaceDto.setRange(range);
            surfaceDtoList.add(surfaceDto);
        }

        Comparator<SurfaceDto> indexComparator = Comparator.comparing(SurfaceDto::getIndex);
        surfaceDtoList.sort(indexComparator);

        return surfaceDtoList;
    }


    @Override
    public String createTxt(String index) throws IOException {
        List<YjfxdzYz> yjfxdzYzs = yjfxdzYzService.listByIndex(index);
        File file = FileUtil.getFile("txt");

        BufferedWriter out = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream(file.getPath(), true)));
        out.write("[因子]" + "\n");
        for (YjfxdzYz yjfxdzYz : yjfxdzYzs) {
            out.write(yjfxdzYz.getId() + "\t"
                    + yjfxdzYz.getIndex() + "\t"
                    + yjfxdzYz.getFactorName() + "\t"
                    + yjfxdzYz.getFactorType() + "\t"
                    + yjfxdzYz.getFactorValue() + "\n");
        }
        out.close();
        return file.getPath();
    }

    @Override
    public Integer getMaxId() {
        String maxid = ybba01aMapper.selectMaxDocByType("2");
        if (maxid == "") maxid = DateTime.now().toDateTimeString("yy") + "000";
        return (Integer.parseInt(maxid) + 1);
    }

    /**
     * 省级产品生成
     *
     * @param issueNum
     * @param userName    传行政编码进来
     * @param yjType
     * @param sXType
     * @param date
     * @param timeChar
     * @param nTimes
     * @param colorAndPos
     * @param posStr
     * @param images
     * @param layerName
     * @param dlData
     * @param type1
     * @return
     * @throws IOException
     * @throws ParseException
     */
    @Override
    public Object createProduct(Integer issueNum,
                                String userName,
                                String yjType,
                                String sXType,
                                String date,
                                String timeChar,
                                Integer nTimes,
                                String colorAndPos,
                                String posStr,
                                MultipartFile[] images,
                                String layerName,
                                String dlData,
                                Integer type1, String point) throws IOException, ParseException {
        //模板路径
        String templatePath;
        //产品路径
        String targetPath;
        //产品图片路径
        String targetImgPath;
        //配置文件路径
        String configFilePath;
        String qx = "";
        String xz = "";
        String ys = "";
        String ling = "";
        String maxid = "";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日HH时");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日HH时mm分");
        SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy年MM月dd日");
        SimpleDateFormat sdf4 = new SimpleDateFormat("yyyyMM");
        SimpleDateFormat sdf5 = new SimpleDateFormat("yyyy");
        Date date1 = sdf.parse(date);
        String year = sdf5.format(date1);
        //获取文档名称
        String productName = "";

        if (type1 == 2) {
            maxid = ybba01aMapper.selectMaxDocByType("4");
            productName = "中短期预警" + sdf2.format(date1) + "预警信息";
            templatePath = nginxFilepath + "Documents/风险预警模板/地质灾害气象风险预警中短期模板.docx";
        } else if (type1 == 1) {
            maxid = ybba01aMapper.selectMaxDocByType("2");
            productName = "短期预警" + sdf2.format(date1) + "预警信息";
            // 是否有风险区
            if (!StringUtil.IsNullOrEmpty(colorAndPos) && colorAndPos.length() > 2) {
                templatePath = nginxFilepath + "Documents/风险预警模板/地质灾害气象风险预警短期模板省级.docx";
            } else {
                templatePath = nginxFilepath + "Documents/风险预警模板/地质灾害气象风险预警短期模板省级无风险区.docx";
            }
        } else {
            maxid = ybba01aMapper.selectMaxDocByType("1");
            productName = "短临预警" + sdf2.format(date1) + "预警信息";
            if (!StringUtil.IsNullOrEmpty(colorAndPos) && colorAndPos.length() > 2) {
                templatePath = nginxFilepath + "Documents/风险预警模板/地质灾害气象风险预警模板.docx";
            } else {
                templatePath = nginxFilepath + "Documents/风险预警模板/地质灾害气象风险预警模板无风险区.docx";
            }
        }
        configFilePath = nginxFilepath + "Documents/风险预警模板/预警内容地灾.ini";
        if (maxid == null || maxid == "") {
            maxid = DateTime.now().toDateTimeString("yy") + "000";
        }
        issueNum = (Integer.parseInt(maxid) + 1);

        targetPath = nginxFilepath + productName + ".docx";
        targetImgPath = nginxFilepath + productName + ".jpg";

        List<Location> map = new ArrayList<>();
        Map<Integer, List<ColorAndNameDto>> colorAndNameMap = new HashMap<>();

        StringBuilder sbyellows = new StringBuilder();
        StringBuilder sborags = new StringBuilder();
        StringBuilder sbreds = new StringBuilder();


        short a = 1;

        if (!StringUtil.IsNullOrEmpty(colorAndPos) && colorAndPos.length() > 2) {
            //json字符串转换为对象列表
            List<ColorAndPos> posList = JSON.parseArray(colorAndPos, ColorAndPos.class);
            //获取预警区内乡镇数据
            for (ColorAndPos typeAndPos : posList) {
                String type = typeAndPos.getColor();
                switch (type) {
                    case "0":
                        StringBuilder sb0 = new StringBuilder();
                        for (double[] po : typeAndPos.getPos()) {
                            sb0.append(po[0]).append(" ").append(po[1]).append(";");
                        }
                        sb0.deleteCharAt(sb0.length() - 1);
                        sbyellows.append(sb0).append("*");
                        break;
                    case "1":
                        StringBuilder sb1 = new StringBuilder();
                        for (double[] po : typeAndPos.getPos()) {
                            sb1.append(po[0]).append(" ").append(po[1]).append(";");
                        }
                        sb1.deleteCharAt(sb1.length() - 1);
                        sborags.append(sb1).append("*");
                        break;
                    case "2":
                        StringBuilder sb2 = new StringBuilder();
                        for (double[] po : typeAndPos.getPos()) {
                            sb2.append(po[0]).append(" ").append(po[1]).append(";");
                        }
                        sb2.deleteCharAt(sb2.length() - 1);
                        sbreds.append(sb2).append("*");
                        break;
                }
            }
        }
        if (sbyellows.length() > 0) sbyellows.deleteCharAt(sbyellows.length() - 1);
        if (sborags.length() > 0) sborags.deleteCharAt(sborags.length() - 1);
        if (sbreds.length() > 0) sbreds.deleteCharAt(sbreds.length() - 1);
        Map<String, StringBuilder> maplevels = new HashMap<>();
        maplevels.put("0", sbyellows);
        maplevels.put("1", sborags);
        maplevels.put("2", sbreds);


        for (String type : maplevels.keySet()) {//keySet获取map集合key的集合
            String color = "";
            String level = "";
            StringBuilder value = maplevels.get(type);//
            switch (type) {
                case "0":
                    color = "黄色";
                    level = "风险较大";
                    break;
                case "1":
                    color = "橙色";
                    level = "风险大";
                    break;
                case "2":
                    color = "红色";
                    level = "风险极大";
                    break;
            }

            if (value.toString().equals(""))
                continue;
            //多边形查询县界面
            map = DmgisUtils.getCountryMap(dmgisIp, dmgisPort, serveName, value);

            for (Location obj : map) {
                ColorAndNameDto colorAndNameDto = new ColorAndNameDto();
                colorAndNameDto.setCounty(obj.getCounty());
                if (obj.getCounty().equals("")) {
                    colorAndNameDto.setCountry(obj.getName());//分析县界面，用name赋值，code用来查询城市
                    colorAndNameDto.setCounty(obj.getCode());
                }
                String code = obj.getCode();
                if (!code.equals("")) {//分析的县界面
                    String cityCode = code.substring(0, 4) + "00";
                    //根据市级code查询市级名称
                    String cityName = zdda01aService.queryCityName(cityCode);
                    qx += cityName + ",";//市
                    xz += obj.getName() + ",";//县
                }
                colorAndNameDto.setType(Integer.parseInt(type));
                ys += level + ",";
                ling += Integer.parseInt(type) + ",";
                colorAndNameDto.setColor(color);
                List<ColorAndNameDto> colorAndNameDtoList = null;
                if (colorAndNameMap.containsKey(Integer.parseInt(type))) {
                    colorAndNameDtoList = colorAndNameMap.get(Integer.parseInt(type));
                } else {
                    colorAndNameDtoList = new ArrayList<>();
                }
                colorAndNameDtoList.add(colorAndNameDto);
                List<ColorAndNameDto> collect = colorAndNameDtoList.stream().distinct().collect(Collectors.toList());
                collect = collect.stream().sorted(Comparator.comparing(ColorAndNameDto::getCounty))
                        .collect(Collectors.toList());
                colorAndNameMap.put(Integer.parseInt(type), collect);
            }
        }

        // 读取配置文件获取正文
        InputStream configStream = new FileInputStream(configFilePath); //使用流来处理
        Wini ini = new Wini(new BufferedReader(new InputStreamReader(configStream, "GBK")));
        Ini.Section section = ini.get("DOCS");
        String docType = "";
        // 只有黄色预警
        if (colorAndNameMap.containsKey(0) && !colorAndNameMap.containsKey(1) && !colorAndNameMap.containsKey(2)) {
            docType = section.get("doc3");
        }
        // 只有橙色预警
        else if (!colorAndNameMap.containsKey(0) && colorAndNameMap.containsKey(1) && !colorAndNameMap.containsKey(2)) {
            docType = section.get("doc2");
        }
        // 只有红色预警
        else if (!colorAndNameMap.containsKey(0) && !colorAndNameMap.containsKey(1) && colorAndNameMap.containsKey(2)) {
            docType = section.get("doc1");
        }
        // 黄色预警和橙色预警
        else if (colorAndNameMap.containsKey(0) && colorAndNameMap.containsKey(1) && !colorAndNameMap.containsKey(2)) {
            docType = section.get("doc23");
        }
        // 黄色预警和红色预警
        else if (colorAndNameMap.containsKey(0) && !colorAndNameMap.containsKey(1) && colorAndNameMap.containsKey(2)) {
            docType = section.get("doc13");
        }
        // 橙色预警和红色预警
        else if (!colorAndNameMap.containsKey(0) && colorAndNameMap.containsKey(1) && colorAndNameMap.containsKey(2)) {
            docType = section.get("doc12");
        }
        // 黄色预警和橙色预警和红色预警
        else if (colorAndNameMap.containsKey(1) && colorAndNameMap.containsKey(2) && colorAndNameMap.containsKey(0)) {
            docType = section.get("doc123");
        }
        // 无风险区
        else {
            docType = section.get("doc4");
        }
        //一级区县内容
        StringBuilder country1 = new StringBuilder();
        //二级区县内容
        StringBuilder country2 = new StringBuilder();
        //三级区县内容
        StringBuilder country3 = new StringBuilder();

        List<ColorAndNameDto> colorAndNameDtoListAll = new ArrayList<>();
        if (colorAndNameMap.containsKey(0)) {
            List<ColorAndNameDto> colorAndNameDtoList = colorAndNameMap.get(0);
            colorAndNameDtoListAll.addAll(colorAndNameDtoList);
            for (ColorAndNameDto colorAndNameDto : colorAndNameDtoList) {
                country1.append(colorAndNameDto.getCountry()).append(",");
            }
            country1.deleteCharAt(country1.length() - 1);

        }
        if (colorAndNameMap.containsKey(1)) {
            List<ColorAndNameDto> colorAndNameDtoList = colorAndNameMap.get(1);
            colorAndNameDtoListAll.addAll(colorAndNameDtoList);
            for (ColorAndNameDto colorAndNameDto : colorAndNameDtoList) {
                country2.append(colorAndNameDto.getCountry()).append(",");
            }
            country2.deleteCharAt(country2.length() - 1);

        }
        if (colorAndNameMap.containsKey(2)) {
            List<ColorAndNameDto> colorAndNameDtoList = colorAndNameMap.get(2);
            colorAndNameDtoListAll.addAll(colorAndNameDtoList);
            for (ColorAndNameDto colorAndNameDto : colorAndNameDtoList) {
                country3.append(colorAndNameDto.getCountry()).append(",");
            }
            country3.deleteCharAt(country3.length() - 1);
        }
        //替换正文内容
        docType = docType.replace("[三级区县]", country1.toString());
        docType = docType.replace("[二级区县]", country2.toString());
        docType = docType.replace("[一级区县]", country3.toString());
        docType = docType.replace("[发布时间]", sdf1.format(new Date()));
        docType = docType.replace("[批号]", String.valueOf(issueNum));
        docType = docType.replace("[预警起报点]", sdf3.format(date1) + timeChar + "时");
        docType = docType.replace("[预警时长]", String.valueOf(nTimes));
        docType = docType.replace("[预警时效]", sdf3.format(date1) + timeChar + "时起" + nTimes + "小时");
        //设置点集合区县内容
        DzWarning dzWarning = new DzWarning();
        dzWarning.setPos(posStr);
        dzWarning.setGradearea3(country1.toString());
        dzWarning.setGradearea4(country2.toString());
        dzWarning.setGradearea5(country3.toString());
        //解析地理分析数据
        List<Object> layerObjectList = new ArrayList<>();
        if (StringUtils.isNotBlank(dlData) && StringUtils.isNotBlank(layerName)) {
            try {
                List<LayerRcoDto1> LayerRcoDtoList = JSON.parseArray(dlData, LayerRcoDto1.class);
                Class layerClass = LayerUtil.getLayerClass(layerName);
                for (LayerRcoDto1 layerRcoDto : LayerRcoDtoList) {
                    JSONObject rcoValObject = (JSONObject) layerRcoDto.getRcoValObject();
                    Object javaObject = JSON.toJavaObject(rcoValObject, layerClass);
                    layerObjectList.add(javaObject);
                }
            } catch (Exception e) {
                System.err.println("地理分析数据解析错误");
            }
        }

        //生成文档
        try {
            InputStream templateInputStream = new FileInputStream(templatePath);
            OutputStream targetOutputStream = new FileOutputStream(targetPath);
            XWPFDocument document = new XWPFDocument(templateInputStream);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

            List<XWPFParagraph> paragraphs = document.getParagraphs();
            String[] placeholders = new String[]{
                    "[年份]",
                    "[文件号]", "[时间1]", "[时间2]", "[预警情况1]", "[时间3]"};
            String[] replacements = new String[]{
                    year,
                    String.valueOf(issueNum), sdf3.format(date1), sdf3.format(date1) + timeChar + "时", docType
                    , sdf3.format(date1)
            };

            for (int i = 0; i < paragraphs.size(); i++) {
                XWPFParagraph paragraph = paragraphs.get(i);
                String text = paragraph.getText();

                DocxUtil.replaceTextInParagraph(paragraph, placeholders, replacements);

                //插入图片
                if (StringUtils.isNotBlank(text) && text.contains("[图1]")) {
                    //获取下标
                    XmlCursor cursor = paragraph.getCTP().newCursor();
                    XWPFParagraph newPara = document.insertNewParagraph(cursor);
                    newPara.setAlignment(ParagraphAlignment.CENTER);//居中
                    XWPFRun newParaRun = newPara.createRun();

                    for (MultipartFile image : images) {
                        //插入图片
                        CTSectPr sectPr = document.getDocument().getBody().getSectPr();
                        CTPageSz pageSize = sectPr.getPgSz();
                        int pageWidth = pageSize.getW().intValue() / 27;
                        //以前高度除以25，现在高度除以50
                        int pageHeight = pageSize.getH().intValue() / 60;
                        newParaRun.addPicture(image.getInputStream(), XWPFDocument.PICTURE_TYPE_PNG, "kill.png,", Units.toEMU(pageWidth), Units.toEMU(pageHeight));
                        FileUtil.bytesToFile(image.getBytes(), targetImgPath);
                    }
                    document.removeBodyElement(document.getPosOfParagraph(paragraph));
                }
                //插入预警区表格
                if (StringUtils.isNotBlank(text) && text.contains("[表1]")) {
                    //获取下标
                    XmlCursor cursor = paragraph.getCTP().newCursor();

                    List<ColorAndNameDto> countryList = new ArrayList<>();
                    //int nrows=0;
                    for (Integer key : colorAndNameMap.keySet()) {//keySet获取map集合key的集合  然后在遍历key即可
                        List<ColorAndNameDto> maplist = colorAndNameMap.get(key);//
                        for (ColorAndNameDto obj : maplist) {
                            countryList.add(obj);
                        }
                    }

                    // 去重，保留最大风险
                    Map<String, ColorAndNameDto> minType = new TreeMap<>();
                    for (ColorAndNameDto obj : countryList) {
                        ColorAndNameDto existing = minType.get(obj.getCountry());
                        if (existing == null || existing.getType() < obj.getType()) {
                            minType.put(obj.getCountry(), obj);
                        }
                    }
                    // 将map的值转换回List
                    List<ColorAndNameDto> uniqueList = new ArrayList<>(minType.values());
                    // 红色预警
                    List<ColorAndNameDto> redList = new ArrayList<>();
                    // 橙色预警
                    List<ColorAndNameDto> orangeList = new ArrayList<>();
                    // 黄色预警
                    List<ColorAndNameDto> yellowList = new ArrayList<>();
                    uniqueList.forEach(l -> {
                        //根据查询出来的code截取前四位来查询数据库找到对应的市级
                        String code = l.getCounty();
                        String cityCode = code.substring(0, 4) + "00";
                        String cityName = zdda01aService.queryCityName(cityCode);
                        l.setCityName(cityName);
                        switch (l.getType()) {
                            case 0:
                                yellowList.add(l);
                                break;
                            case 1:
                                orangeList.add(l);
                                break;
                            case 2:
                                redList.add(l);
                                break;
                        }
                    });
                    // 按行政编码排序
                    Collections.sort(yellowList, new Comparator<ColorAndNameDto>() {
                        @Override
                        public int compare(ColorAndNameDto o1, ColorAndNameDto o2) {
                            return o1.getCityName().compareTo(o2.getCityName());
                        }
                    });
                    Collections.sort(orangeList, new Comparator<ColorAndNameDto>() {
                        @Override
                        public int compare(ColorAndNameDto o1, ColorAndNameDto o2) {
                            return o1.getCityName().compareTo(o2.getCityName());
                        }
                    });
                    Collections.sort(redList, new Comparator<ColorAndNameDto>() {
                        @Override
                        public int compare(ColorAndNameDto o1, ColorAndNameDto o2) {
                            return o1.getCityName().compareTo(o2.getCityName());
                        }
                    });
                    List<ColorAndNameDto> allList = new ArrayList<>();
                    allList.addAll(redList);
                    allList.addAll(orangeList);
                    allList.addAll(yellowList);

                    if (allList.size() > 0) {

                        XWPFTable table = document.insertNewTbl(cursor);
                        //添加表头
                        XWPFTableRow row_0 = table.getRow(0);
                        row_0.getCell(0).setText("市");
                        row_0.addNewTableCell().setText("区县");
                        row_0.addNewTableCell().setText("预警等级");

                        String oldCityName = "";
                        for (int m = 0; m < allList.size(); m++) {
                            ColorAndNameDto location = allList.get(m);
                            XWPFTableRow dataRow = table.createRow();
                            String cityName = location.getCityName();
                            if (!oldCityName.equals(cityName)) {
                                dataRow.getCell(0).setText(location.getCityName());
                                dataRow.getCell(0).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
                                oldCityName = cityName;
                            } else {
                                dataRow.getCell(0).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
                            }
                            dataRow.getCell(1).setText(location.getCountry());
                            switch (location.getType()) {
                                case 0:
                                    dataRow.getCell(2).setText("风险较大（黄色预警）");
                                    break;
                                case 1:
                                    dataRow.getCell(2).setText("风险大（橙色预警）");
                                    break;
                                case 2:
                                    dataRow.getCell(2).setText("风险极大（红色预警）");
                                    break;
                            }
                        }
                        //DocxUtil.mergeTable(table,nrows+1,1);
                        DocxUtil.setTableLocation(table, "center");
                        DocxUtil.setCellLocation(table, "CENTER", "center");
                    }
                    document.removeBodyElement(document.getPosOfParagraph(paragraph));
                }

                //插入地灾隐患点表格
                if (StringUtils.isNotBlank(text) && text.contains("灾害点")) {

                    //获取下标
                    XmlCursor cursor = paragraph.getCTP().newCursor();


                    List<DisasterTypeNumVo> list = zdda01aService.dzTable(point, userName);
                    if (list != null && list.size() > 0) {

                        XWPFTable table = document.insertNewTbl(cursor);
                        //添加表头
                        XWPFTableRow row_0 = table.getRow(0);
                        row_0.getCell(0).setText("市");
                        row_0.addNewTableCell().setText("区县");
                        row_0.addNewTableCell().setText("总数");
                        row_0.addNewTableCell().setText("滑坡");
                        row_0.addNewTableCell().setText("崩塌");
                        row_0.addNewTableCell().setText("泥石流");

                        String oldCode = "";
                        for (DisasterTypeNumVo disaster : list) {
                            XWPFTableRow dataRow = table.createRow();
                            String cityCode = disaster.getCityCode().toString();
                            if (cityCode.compareTo(oldCode) != 0) {
                                dataRow.getCell(0).setText(disaster.getCityName());
                                dataRow.getCell(0).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
                                oldCode = cityCode;
                            } else {
                                dataRow.getCell(0).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
                            }
                            dataRow.getCell(1).setText(disaster.getCountyName());
                            dataRow.getCell(2).setText(disaster.getSum().toString());
                            dataRow.getCell(3).setText(disaster.getHp().toString());
                            dataRow.getCell(4).setText(disaster.getBt().toString());
                            dataRow.getCell(5).setText(disaster.getNsl().toString());
                        }
                        DocxUtil.setTableLocation(table, "center");
                        DocxUtil.setCellLocation(table, "CENTER", "center");
                    }

                    document.removeBodyElement(document.getPosOfParagraph(paragraph));
                }

                //插入地理分析数据表格
                if (layerObjectList.size() > 0 && StringUtils.isNotBlank(text) && text.contains("[预警信息表]")) {
                    //获取下标
                    XmlCursor cursor = paragraph.getCTP().newCursor();
                    XWPFTable table = document.insertNewTbl(cursor);
                    //插入图层表格数据
                    DocxUtil.insertTablaLayerData(layerName, layerObjectList, table);
                    DocxUtil.setTableLocation(table, "center");
                    DocxUtil.setCellLocation(table, "CENTER", "center");
                    document.removeBodyElement(document.getPosOfParagraph(paragraph));
                }
            }
            // 将生成的文档保存到输出文件
            document.write(targetOutputStream);

            // 创建时间
            Date datetime = new Date();
            // 将时间转为 LocalDateTime
            LocalDateTime localDateTime = datetime.toInstant().atOffset(ZoneOffset.ofHours(8)).toLocalDateTime();
            Ybba02a ybba02a = new Ybba02a();
            ybba02a.setYbba02a010(UUID.randomUUID().toString().replace("-", ""));//获取时分秒当id
            ybba02a.setYbba02a020(productName);
            ybba02a.setYbba02a030(localDateTime);
            ybba02a.setYbba02a040("");//预警方位东南西北，不分析方位信息
            ybba02a.setYbba02a050(ling);//预警级别0,0
            ybba02a.setYbba02a060(ys);//预警类型风险大，风险较大，风险极大
            ybba02a.setYbba02a070(qx);///市州
            ybba02a.setYbba02a080(xz);//区县
            ybba02a.setYbba02a090(colorAndPos.getBytes());//预警坐标
            ybba02a.setYbba02a100("");//预警标注
            ybba02a.setYbba02a035("");//预警时效，24小时默认为空
            //入库
            int insertcount = ybba02aMapper.insert(ybba02a);

            byte[] buffer = new byte[1024];
            int bytesRead;
            FileInputStream inputStream = new FileInputStream(targetPath);
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, bytesRead);
            }
            byte[] byteArray = byteArrayOutputStream.toByteArray();

            File targetfile = new File(targetPath);
            //设置可执行权限
            targetfile.setExecutable(true, false);
            //设置可读权限
            targetfile.setReadable(true, false);
            //设置可写权限
            targetfile.setWritable(true, false);

            // 设置前端响应
            HttpHeaders headers = new HttpHeaders();
            headers.setContentDispositionFormData("attachment", productName + ".docx");
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentLength(byteArray.length);

            return new ResponseEntity<>(byteArray, headers, HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("文档生成失败");
        }
        return null;
    }

    /**
     * 市级产品生成
     *
     * @param issueNum
     * @param userName
     * @param yjType
     * @param sXType
     * @param date
     * @param timeChar
     * @param nTimes
     * @param colorAndPos
     * @param images
     * @param layerName
     * @param dlData
     * @param type1
     * @return
     * @throws IOException
     * @throws ParseException
     */
    @Override
    public Object createProduct1(Integer issueNum, String userName, String yjType, String sXType, String date, String timeChar, Integer nTimes, String colorAndPos, String posStr, MultipartFile[] images, String layerName, String dlData, Integer type1, String point) throws IOException, ParseException {
        //模板路径
        String templatePath;
        //产品路径
        String targetPath;
        //产品图片路径
        String targetImgPath;
        //配置文件路径
        String configFilePath;
        String qx = "";
        String xz = "";
        String ys = "";
        String ling = "";
        String maxid = "";

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日HH时");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日HH时mm分");
        SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy年MM月dd日");
        SimpleDateFormat sdf4 = new SimpleDateFormat("yyyyMM");
        SimpleDateFormat sdf5 = new SimpleDateFormat("yyyy");
        Date date1 = sdf.parse(date);
        String year = sdf5.format(date1);

        //获取文档名称
        String productName = "";

        if (type1 == 2) {
            maxid = ybba01bMapper.selectMaxDocByType("4", userName);
            productName = "中短期预警" + sdf2.format(date1) + "预警信息";
            templatePath = nginxFilepath + "Documents/风险预警模板/地质灾害气象风险预警中短期模板.docx";
        } else if (type1 == 1) {
            maxid = ybba01bMapper.selectMaxDocByType("2", userName);
            productName = "短期预警" + sdf2.format(date1) + "预警信息";
            // 无风险区
            if (!StringUtil.IsNullOrEmpty(colorAndPos) && colorAndPos.length() > 2) {
                templatePath = nginxFilepath + "Documents/风险预警模板/地质灾害气象风险预警短期模板市级灾害点.docx";
            } else {
                templatePath = nginxFilepath + "Documents/风险预警模板/地质灾害气象风险预警短期模板市级无风险区.docx";
            }
        } else {
            maxid = ybba01bMapper.selectMaxDocByType("1", userName);
            productName = "短临预警" + sdf2.format(date1) + "预警信息";
            // 无风险区
            if (!StringUtil.IsNullOrEmpty(colorAndPos) && colorAndPos.length() > 2) {
                templatePath = nginxFilepath + "Documents/风险预警模板/地质灾害气象风险预警模板市县级.docx";
            } else {
                templatePath = nginxFilepath + "Documents/风险预警模板/地质灾害气象风险预警模板市县级无风险区.docx";
            }
        }
        if (maxid == null || maxid == "") {
            maxid = DateTime.now().toDateTimeString("yy") + "000";
        }
        issueNum = (Integer.parseInt(maxid) + 1);

        configFilePath = nginxFilepath + "Documents/风险预警模板/预警内容地灾市级.ini";

        targetPath = nginxFilepath + productName + ".docx";
        targetImgPath = nginxFilepath + productName + ".jpg";

        List<Location> map = new ArrayList<>();
        Map<Integer, List<ColorAndNameDto>> colorAndNameMap = new HashMap<>();


        StringBuilder sbyellows = new StringBuilder();
        StringBuilder sborags = new StringBuilder();
        StringBuilder sbreds = new StringBuilder();

        //获取预警区内乡镇数据
        if (!StringUtil.IsNullOrEmpty(colorAndPos) && colorAndPos.length() > 2) {
            //json字符串转换为对象列表
            List<ColorAndPos> posList = JSON.parseArray(colorAndPos, ColorAndPos.class);
            for (ColorAndPos typeAndPos : posList) {
                String type = typeAndPos.getColor();
                switch (type) {
                    case "0":
                        StringBuilder sb0 = new StringBuilder();
                        for (double[] po : typeAndPos.getPos()) {
                            sb0.append(po[0]).append(" ").append(po[1]).append(";");
                        }
                        sb0.deleteCharAt(sb0.length() - 1);
                        sbyellows.append(sb0).append("*");
                        break;
                    case "1":
                        StringBuilder sb1 = new StringBuilder();
                        for (double[] po : typeAndPos.getPos()) {
                            sb1.append(po[0]).append(" ").append(po[1]).append(";");
                        }
                        sb1.deleteCharAt(sb1.length() - 1);
                        sborags.append(sb1).append("*");
                        break;
                    case "2":
                        StringBuilder sb2 = new StringBuilder();
                        for (double[] po : typeAndPos.getPos()) {
                            sb2.append(po[0]).append(" ").append(po[1]).append(";");
                        }
                        sb2.deleteCharAt(sb2.length() - 1);
                        sbreds.append(sb2).append("*");
                        break;
                }
            }
        }
        if (sbyellows.length() > 0) sbyellows.deleteCharAt(sbyellows.length() - 1);
        if (sborags.length() > 0) sborags.deleteCharAt(sborags.length() - 1);
        if (sbreds.length() > 0) sbreds.deleteCharAt(sbreds.length() - 1);
        Map<String, StringBuilder> maplevels = new HashMap<>();
        maplevels.put("0", sbyellows);
        maplevels.put("1", sborags);
        maplevels.put("2", sbreds);

        for (String type : maplevels.keySet()) {
            String color = "";
            String level = "";
            StringBuilder value = maplevels.get(type);//
            switch (type) {
                case "0":
                    color = "黄色";
                    level = "风险较大";
                    break;
                case "1":
                    color = "橙色";
                    level = "风险大";
                    break;
                case "2":
                    color = "红色";
                    level = "风险极大";
                    break;
            }

            if (value.toString().equals(""))
                continue;
            //多边形查询乡界面
            map = DmgisUtils.getCountryMapCountry(dmgisIp, dmgisPort, serveName, value);

            for (Location obj : map) {
                ColorAndNameDto colorAndNameDto = new ColorAndNameDto();
                colorAndNameDto.setCounty(obj.getCounty());
                qx += obj.getCountry() + ",";
                xz += obj.getTown() + ",";
                colorAndNameDto.setCounty(obj.getCountry());
                colorAndNameDto.setCountry(obj.getTown());
                colorAndNameDto.setType(Integer.parseInt(type));
                ys += level + ",";
                ling += Integer.parseInt(type) + ",";
                colorAndNameDto.setColor(color);
                List<ColorAndNameDto> colorAndNameDtoList = null;
                if (colorAndNameMap.containsKey(Integer.parseInt(type))) {
                    colorAndNameDtoList = colorAndNameMap.get(Integer.parseInt(type));
                } else {
                    colorAndNameDtoList = new ArrayList<>();
                }
                colorAndNameDtoList.add(colorAndNameDto);
                List<ColorAndNameDto> collect = colorAndNameDtoList.stream().distinct().collect(Collectors.toList());
                collect = collect.stream().sorted(Comparator.comparing(ColorAndNameDto::getCounty))
                        .collect(Collectors.toList());
                colorAndNameMap.put(Integer.parseInt(type), collect);
            }
        }


        //读取配置文件获取正文
        InputStream configStream = new FileInputStream(configFilePath);
        Wini ini = new Wini(new BufferedReader(new InputStreamReader(configStream, "GBK")));
        Ini.Section section = ini.get("DOCS");
        String docType = "";
        // 只有黄色预警
        if (colorAndNameMap.containsKey(0) && !colorAndNameMap.containsKey(1) && !colorAndNameMap.containsKey(2)) {
            docType = section.get("doc3");
        }
        // 只有橙色预警
        else if (!colorAndNameMap.containsKey(0) && colorAndNameMap.containsKey(1) && !colorAndNameMap.containsKey(2)) {
            docType = section.get("doc2");
        }
        // 只有红色预警
        else if (!colorAndNameMap.containsKey(0) && !colorAndNameMap.containsKey(1) && colorAndNameMap.containsKey(2)) {
            docType = section.get("doc1");
        }
        // 黄色预警和橙色预警
        else if (colorAndNameMap.containsKey(0) && colorAndNameMap.containsKey(1) && !colorAndNameMap.containsKey(2)) {
            docType = section.get("doc23");
        }
        // 黄色预警和红色预警
        else if (colorAndNameMap.containsKey(0) && !colorAndNameMap.containsKey(1) && colorAndNameMap.containsKey(2)) {
            docType = section.get("doc13");
        }
        // 橙色预警和红色预警
        else if (!colorAndNameMap.containsKey(0) && colorAndNameMap.containsKey(1) && colorAndNameMap.containsKey(2)) {
            docType = section.get("doc12");
        }
        // 黄色预警和橙色预警和红色预警
        else if (colorAndNameMap.containsKey(1) && colorAndNameMap.containsKey(2) && colorAndNameMap.containsKey(0)) {
            docType = section.get("doc123");
        }
        // 无风险区
        else {
            docType = section.get("doc4");
        }
        //一级区县内容
        StringBuilder country1 = new StringBuilder();
        //二级区县内容
        StringBuilder country2 = new StringBuilder();
        //三级区县内容
        StringBuilder country3 = new StringBuilder();

        List<ColorAndNameDto> colorAndNameDtoListAll = new ArrayList<>();
        if (colorAndNameMap.containsKey(0)) {
            List<ColorAndNameDto> colorAndNameDtoList = colorAndNameMap.get(0);
            colorAndNameDtoListAll.addAll(colorAndNameDtoList);
            for (ColorAndNameDto colorAndNameDto : colorAndNameDtoList) {
                country1.append(colorAndNameDto.getCountry()).append(",");
            }
            country1.deleteCharAt(country1.length() - 1);

        }
        if (colorAndNameMap.containsKey(1)) {
            List<ColorAndNameDto> colorAndNameDtoList = colorAndNameMap.get(1);
            colorAndNameDtoListAll.addAll(colorAndNameDtoList);
            for (ColorAndNameDto colorAndNameDto : colorAndNameDtoList) {
                country2.append(colorAndNameDto.getCountry()).append(",");
            }
            country2.deleteCharAt(country2.length() - 1);

        }
        if (colorAndNameMap.containsKey(2)) {
            List<ColorAndNameDto> colorAndNameDtoList = colorAndNameMap.get(2);
            colorAndNameDtoListAll.addAll(colorAndNameDtoList);
            for (ColorAndNameDto colorAndNameDto : colorAndNameDtoList) {
                country3.append(colorAndNameDto.getCountry()).append(",");
            }
            country3.deleteCharAt(country3.length() - 1);
        }
        //替换正文内容
        String cityName = zdda01aService.queryCityName(userName);
        docType = docType.replace("[行政]", cityName);
        docType = docType.replace("[三级区县]", country1.toString());
        docType = docType.replace("[二级区县]", country2.toString());
        docType = docType.replace("[一级区县]", country3.toString());
        docType = docType.replace("[发布时间]", sdf1.format(new Date()));
        docType = docType.replace("[批号]", String.valueOf(issueNum));
        docType = docType.replace("[预警起报点]", sdf3.format(date1) + timeChar + "时");
        docType = docType.replace("[预警时长]", String.valueOf(nTimes));
        docType = docType.replace("[预警时效]", sdf3.format(date1) + timeChar + "时起" + nTimes + "小时");
        //解析地理分析数据
        List<Object> layerObjectList = new ArrayList<>();
        if (StringUtils.isNotBlank(dlData) && StringUtils.isNotBlank(layerName)) {
            try {
                List<LayerRcoDto> LayerRcoDtoList = JSON.parseArray(dlData, LayerRcoDto.class);
                Class layerClass = LayerUtil.getLayerClass(layerName);
                for (LayerRcoDto layerRcoDto : LayerRcoDtoList) {
                    JSONObject rcoValObject = (JSONObject) layerRcoDto.getRcoValObject();
                    Object javaObject = JSON.toJavaObject(rcoValObject, layerClass);
                    layerObjectList.add(javaObject);
                }
            } catch (Exception e) {
                System.err.println("地理分析数据解析错误");
            }
        }

        //生成文档
        try (
                InputStream templateInputStream = new FileInputStream(templatePath);
                OutputStream targetOutputStream = new FileOutputStream(targetPath);
                XWPFDocument document = new XWPFDocument(templateInputStream);
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ) {
            List<XWPFParagraph> paragraphs = document.getParagraphs();
            //段落替换
            String[] placeholders = new String[]{
                    "[行政]",
                    "[年份]",
                    "[文件号]", "[时间1]", "[时间2]", "[预警情况1]", "[时间3]"};
            String[] replacements = new String[]{
                    cityName,
                    year,
                    String.valueOf(issueNum), sdf3.format(date1), sdf3.format(date1) + timeChar + "时", docType
                    , sdf3.format(date1)
            };

            for (int i = 0; i < paragraphs.size(); i++) {
                XWPFParagraph paragraph = paragraphs.get(i);
                String text = paragraph.getText();

                DocxUtil.replaceTextInParagraph(paragraph, placeholders, replacements);


                //插入图片
                if (StringUtils.isNotBlank(text) && text.contains("[图1]")) {
                    //获取下标
                    XmlCursor cursor = paragraph.getCTP().newCursor();
                    XWPFParagraph newPara = document.insertNewParagraph(cursor);
                    newPara.setAlignment(ParagraphAlignment.CENTER);//居中
                    XWPFRun newParaRun = newPara.createRun();

                    for (MultipartFile image : images) {
                        //插入图片
                        CTSectPr sectPr = document.getDocument().getBody().getSectPr();
                        CTPageSz pageSize = sectPr.getPgSz();
                        int pageWidth = pageSize.getW().intValue() / 27;
                        //以前高度除以25，现在高度除以50
                        int pageHeight = pageSize.getH().intValue() / 60;
                        newParaRun.addPicture(image.getInputStream(), XWPFDocument.PICTURE_TYPE_PNG, "kill.png,", Units.toEMU(pageWidth), Units.toEMU(pageHeight));
                        FileUtil.bytesToFile(image.getBytes(), targetImgPath);
                    }
                    document.removeBodyElement(document.getPosOfParagraph(paragraph));
                }
                //插入预警区表格
                if (StringUtils.isNotBlank(text) && text.contains("[表1]")) {
                    //获取下标
                    XmlCursor cursor = paragraph.getCTP().newCursor();

                    // 去重，保留最大风险
                    Map<String, ColorAndNameDto> minType = new TreeMap<>();
                    for (ColorAndNameDto obj : colorAndNameDtoListAll) {
                        ColorAndNameDto existing = minType.get(obj.getCountry());
                        if (existing == null || existing.getType() < obj.getType()) {
                            minType.put(obj.getCountry(), obj);
                        }
                    }

                    // 将map的值转换回List
                    List<ColorAndNameDto> uniqueList = new ArrayList<>(minType.values());

                    // 红色预警
                    List<ColorAndNameDto> redList = new ArrayList<>();
                    // 橙色预警
                    List<ColorAndNameDto> orangeList = new ArrayList<>();
                    // 黄色预警
                    List<ColorAndNameDto> yellowList = new ArrayList<>();
                    uniqueList.forEach(l -> {
                        switch (l.getType()) {
                            case 0:
                                yellowList.add(l);
                                break;
                            case 1:
                                orangeList.add(l);
                                break;
                            case 2:
                                redList.add(l);
                                break;
                        }
                    });
                    // 按行政编码排序
                    Collections.sort(yellowList, new Comparator<ColorAndNameDto>() {
                        @Override
                        public int compare(ColorAndNameDto o1, ColorAndNameDto o2) {
                            return o1.getCounty().compareTo(o2.getCounty());
                        }
                    });
                    Collections.sort(orangeList, new Comparator<ColorAndNameDto>() {
                        @Override
                        public int compare(ColorAndNameDto o1, ColorAndNameDto o2) {
                            return o1.getCounty().compareTo(o2.getCounty());
                        }
                    });
                    Collections.sort(redList, new Comparator<ColorAndNameDto>() {
                        @Override
                        public int compare(ColorAndNameDto o1, ColorAndNameDto o2) {
                            return o1.getCounty().compareTo(o2.getCounty());
                        }
                    });
                    List<ColorAndNameDto> allList = new ArrayList<>();
                    allList.addAll(redList);
                    allList.addAll(orangeList);
                    allList.addAll(yellowList);

                    if (allList.size() > 0) {

                        XWPFTable table = document.insertNewTbl(cursor);
                        //添加表头
                        XWPFTableRow row_0 = table.getRow(0);
                        row_0.getCell(0).setText("区县");
                        row_0.addNewTableCell().setText("乡镇");
                        row_0.addNewTableCell().setText("预警等级");

                        String oldCountyName = "";
                        for (ColorAndNameDto country : allList) {
                            XWPFTableRow dataRow = table.createRow();
                            String countyName = country.getCounty();
                            if (!oldCountyName.equals(countyName)) {
                                dataRow.getCell(0).setText(countyName);
                                dataRow.getCell(0).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
                                oldCountyName = countyName;
                            } else {
                                dataRow.getCell(0).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
                            }
                            dataRow.getCell(1).setText(country.getCountry());
                            switch (country.getColor()) {
                                case "黄色":
                                    dataRow.getCell(2).setText("风险较大（黄色预警）");
                                    break;
                                case "橙色":
                                    dataRow.getCell(2).setText("风险大（橙色预警）");
                                    break;
                                case "红色":
                                    dataRow.getCell(2).setText("风险极大（红色预警）");
                                    break;
                            }
                        }
                        DocxUtil.setTableLocation(table, "center");
                        DocxUtil.setCellLocation(table, "CENTER", "center");
                    }

                    document.removeBodyElement(document.getPosOfParagraph(paragraph));
                }

                //插入地灾隐患点表格
                if (StringUtils.isNotBlank(text) && text.contains("灾害点")) {
                    //获取下标
                    XmlCursor cursor = paragraph.getCTP().newCursor();


                    List<DisasterTypeNumVo> list = zdda01aService.dzTable(point, userName);
                    if (list != null && list.size() > 0) {
                        XWPFTable table = document.insertNewTbl(cursor);
                        //添加表头
                        XWPFTableRow row_0 = table.getRow(0);
                        row_0.getCell(0).setText("区县");
                        row_0.addNewTableCell().setText("乡镇");
                        row_0.addNewTableCell().setText("总数");
                        row_0.addNewTableCell().setText("滑坡");
                        row_0.addNewTableCell().setText("崩塌");
                        row_0.addNewTableCell().setText("泥石流");
                        String oldCode = "";
                        for (DisasterTypeNumVo disaster : list) {
                            XWPFTableRow dataRow = table.createRow();
                            String countyCode = disaster.getCountyCode().toString();
                            if (countyCode.compareTo(oldCode) != 0) {
                                dataRow.getCell(0).setText(disaster.getCountyName());
                                dataRow.getCell(0).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
                                oldCode = countyCode;
                            } else {
                                dataRow.getCell(0).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
                            }
                            dataRow.getCell(0).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
                            dataRow.getCell(1).setText(disaster.getTownName());
                            dataRow.getCell(2).setText(disaster.getSum().toString());
                            dataRow.getCell(3).setText(disaster.getHp().toString());
                            dataRow.getCell(4).setText(disaster.getBt().toString());
                            dataRow.getCell(5).setText(disaster.getNsl().toString());
                        }
                        DocxUtil.setTableLocation(table, "center");
                        DocxUtil.setCellLocation(table, "CENTER", "center");
                    }

                    document.removeBodyElement(document.getPosOfParagraph(paragraph));
                }

                //插入地理分析数据表格
                if (layerObjectList.size() > 0 && StringUtils.isNotBlank(text) && text.contains("[预警信息表]")) {
                    //获取下标
                    XmlCursor cursor = paragraph.getCTP().newCursor();
                    XWPFTable table = document.insertNewTbl(cursor);
                    //插入图层表格数据
                    DocxUtil.insertTablaLayerData(layerName, layerObjectList, table);
                    DocxUtil.setTableLocation(table, "center");
                    DocxUtil.setCellLocation(table, "CENTER", "center");
                    document.removeBodyElement(document.getPosOfParagraph(paragraph));

                }
            }
            // 将生成的文档保存到输出文件
            document.write(targetOutputStream);

            //获取文档名称

            Date datetime = new Date();
            // 将时间转为 LocalDateTime
            LocalDateTime localDateTime = datetime.toInstant().atOffset(ZoneOffset.ofHours(8)).toLocalDateTime();
            Ybba02b ybba02b = new Ybba02b();
            ybba02b.setYbba02b010(new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(new Date()));//获取时分秒当id
            ybba02b.setYbba02b020(productName);
            ybba02b.setYbba02b030(localDateTime);
            ybba02b.setYbba02b040("");//预警区域
            ybba02b.setYbba02b050(ling);//预警颜色
            ybba02b.setYbba02b060(ys);//预警等级
            ybba02b.setYbba02b070(qx);//预警所属县
            ybba02b.setYbba02b080(colorAndPos.getBytes());//预警方位
            ybba02b.setYbba02b090(userName);//市编码
            ybba02b.setYbba02b100(xz);//预警所属乡
            ybba02b.setYbba02b110("");//文本信息
            ybba02b.setYbba02b120(type1);// 0：短临，1：短期，2：中短期
            ybba02bMapper.insert(ybba02b);

            byte[] buffer = new byte[1024];
            int bytesRead;
            FileInputStream inputStream = new FileInputStream(targetPath);
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, bytesRead);
            }
            byte[] byteArray = byteArrayOutputStream.toByteArray();
            File targetfile = new File(targetPath);
            //设置可执行权限
            boolean exec = targetfile.setExecutable(true, false);
            //设置可读权限
            boolean read = targetfile.setReadable(true, false);
            //设置可写权限
            boolean write = targetfile.setWritable(true, false);

            // 设置前端响应
            HttpHeaders headers = new HttpHeaders();
            headers.setContentDispositionFormData("attachment", productName + ".docx");
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentLength(byteArray.length);

            return new ResponseEntity<>(byteArray, headers, HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("文档生成失败");
        }

        return null;

    }

    /**
     * 县级产品生成
     *
     * @param issueNum
     * @param userName
     * @param yjType
     * @param sXType
     * @param date
     * @param timeChar
     * @param nTimes
     * @param colorAndPos
     * @param posStr
     * @param images
     * @param layerName
     * @param dlData
     * @param type1
     * @return
     * @throws IOException
     * @throws ParseException
     */
    @Override
    public Object createProduct2(Integer issueNum, String userName, String yjType, String sXType, String date, String timeChar, Integer nTimes, String colorAndPos, String posStr, MultipartFile[] images, String layerName, String dlData, Integer type1, String point) throws IOException, ParseException {
        //模板路径
        String templatePath;
        //产品路径
        String targetPath;
        //产品图片路径
        String targetImgPath;
        //配置文件路径
        String configFilePath;
        String qx = "";
        String xz = "";
        String ys = "";
        String ling = "";

        String maxid = "";

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日HH时");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日HH时mm分");
        SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy年MM月dd日");
        SimpleDateFormat sdf4 = new SimpleDateFormat("yyyyMM");
        SimpleDateFormat sdf5 = new SimpleDateFormat("yyyy");
        Date date1 = sdf.parse(date);
        String year = sdf5.format(date1);
        //获取文档名称
        String productName = "";

        if (type1 == 2) {
            maxid = ybba01cMapper.selectMaxDocByType("4", userName);
            productName = "中短期预警" + sdf2.format(date1) + "预警信息";
            templatePath = nginxFilepath + "Documents/风险预警模板/地质灾害气象风险预警中短期模板.docx";
        } else if (type1 == 1) {
            maxid = ybba01cMapper.selectMaxDocByType("2", userName);
            productName = "短期预警" + sdf2.format(date1) + "预警信息";
            // 无风险区
            if (!StringUtil.IsNullOrEmpty(colorAndPos) && colorAndPos.length() > 2) {
                templatePath = nginxFilepath + "Documents/风险预警模板/地质灾害气象风险预警短期模板县级灾害点.docx";
            } else {
                templatePath = nginxFilepath + "Documents/风险预警模板/地质灾害气象风险预警短期模板县级无风险区.docx";
            }
        } else {
            maxid = ybba01cMapper.selectMaxDocByType("1", userName);
            productName = "短临预警" + sdf2.format(date1) + "预警信息";
            // 无风险区
            if (!StringUtil.IsNullOrEmpty(colorAndPos) && colorAndPos.length() > 2) {
                templatePath = nginxFilepath + "Documents/风险预警模板/地质灾害气象风险预警模板市县级.docx";
            } else {
                templatePath = nginxFilepath + "Documents/风险预警模板/地质灾害气象风险预警模板市县级无风险区.docx";
            }
        }
        configFilePath = nginxFilepath + "Documents/风险预警模板/预警内容地灾县级.ini";
        if (maxid == null || maxid == "") {
            maxid = DateTime.now().toDateTimeString("yy") + "000";
        }
        issueNum = (Integer.parseInt(maxid) + 1);

        targetPath = nginxFilepath + productName + ".docx";
        targetImgPath = nginxFilepath + productName + ".jpg";

        List<Location> map = new ArrayList<>();
        Map<Integer, List<ColorAndNameDto>> colorAndNameMap = new HashMap<>();

        StringBuilder sbyellows = new StringBuilder();
        StringBuilder sborags = new StringBuilder();
        StringBuilder sbreds = new StringBuilder();

        //获取预警区内乡镇数据
        if (!StringUtil.IsNullOrEmpty(colorAndPos) && colorAndPos.length() > 2) {
            //json字符串转换为对象列表
            List<ColorAndPos> posList = JSON.parseArray(colorAndPos, ColorAndPos.class);
            for (ColorAndPos typeAndPos : posList) {
                String type = typeAndPos.getColor();
                switch (type) {
                    case "0":
                        StringBuilder sb0 = new StringBuilder();
                        for (double[] po : typeAndPos.getPos()) {
                            sb0.append(po[0]).append(" ").append(po[1]).append(";");
                        }
                        sb0.deleteCharAt(sb0.length() - 1);
                        sbyellows.append(sb0).append("*");
                        break;
                    case "1":
                        StringBuilder sb1 = new StringBuilder();
                        for (double[] po : typeAndPos.getPos()) {
                            sb1.append(po[0]).append(" ").append(po[1]).append(";");
                        }
                        sb1.deleteCharAt(sb1.length() - 1);
                        sborags.append(sb1).append("*");
                        break;
                    case "2":
                        StringBuilder sb2 = new StringBuilder();
                        for (double[] po : typeAndPos.getPos()) {
                            sb2.append(po[0]).append(" ").append(po[1]).append(";");
                        }
                        sb2.deleteCharAt(sb2.length() - 1);
                        sbreds.append(sb2).append("*");
                        break;
                }
            }
        }
        if (sbyellows.length() > 0) sbyellows.deleteCharAt(sbyellows.length() - 1);
        if (sborags.length() > 0) sborags.deleteCharAt(sborags.length() - 1);
        if (sbreds.length() > 0) sbreds.deleteCharAt(sbreds.length() - 1);
        Map<String, StringBuilder> maplevels = new HashMap<>();
        maplevels.put("0", sbyellows);
        maplevels.put("1", sborags);
        maplevels.put("2", sbreds);

        for (String type : maplevels.keySet()) {//keySet获取map集合key的集合  然后在遍历key即可
            String color = "";
            String level = "";
            StringBuilder value = maplevels.get(type);//
            switch (type) {
                case "0":
                    color = "黄色";
                    level = "风险较大";
                    break;
                case "1":
                    color = "橙色";
                    level = "风险大";
                    break;
                case "2":
                    color = "红色";
                    level = "风险极大";
                    break;
            }

            if (value.toString().equals(""))
                continue;
            map = DmgisUtils.getMapAnalysis(dmgisIp, dmgisPort, serveName, value, "村庄");

            for (Location obj : map) {
                ColorAndNameDto colorAndNameDto = new ColorAndNameDto();
                colorAndNameDto.setCounty(obj.getTown());
                qx += obj.getName() + ",";//村庄
                xz += obj.getTown() + ",";//乡镇
                colorAndNameDto.setCountry(obj.getName());
                colorAndNameDto.setType(Integer.parseInt(type));
                ys += level + ",";
                ling += Integer.parseInt(type) + ",";
                colorAndNameDto.setColor(color);
                List<ColorAndNameDto> colorAndNameDtoList = null;
                if (colorAndNameMap.containsKey(Integer.parseInt(type))) {
                    colorAndNameDtoList = colorAndNameMap.get(Integer.parseInt(type));
                } else {
                    colorAndNameDtoList = new ArrayList<>();
                }
                colorAndNameDtoList.add(colorAndNameDto);
                List<ColorAndNameDto> collect = colorAndNameDtoList.stream().distinct().collect(Collectors.toList());
                collect = collect.stream().sorted(Comparator.comparing(ColorAndNameDto::getCounty))
                        .collect(Collectors.toList());
                colorAndNameMap.put(Integer.parseInt(type), collect);
            }
        }


        //读取配置文件获取正文
        InputStream configStream = new FileInputStream(configFilePath);
        Wini ini = new Wini(new BufferedReader(new InputStreamReader(configStream, "GBK")));
        Ini.Section section = ini.get("DOCS");
        String docType = "";
        // 只有黄色预警
        if (colorAndNameMap.containsKey(0) && !colorAndNameMap.containsKey(1) && !colorAndNameMap.containsKey(2)) {
            docType = section.get("doc3");
        }
        // 只有橙色预警
        else if (!colorAndNameMap.containsKey(0) && colorAndNameMap.containsKey(1) && !colorAndNameMap.containsKey(2)) {
            docType = section.get("doc2");
        }
        // 只有红色预警
        else if (!colorAndNameMap.containsKey(0) && !colorAndNameMap.containsKey(1) && colorAndNameMap.containsKey(2)) {
            docType = section.get("doc1");
        }
        // 黄色预警和橙色预警
        else if (colorAndNameMap.containsKey(0) && colorAndNameMap.containsKey(1) && !colorAndNameMap.containsKey(2)) {
            docType = section.get("doc23");
        }
        // 黄色预警和红色预警
        else if (colorAndNameMap.containsKey(0) && !colorAndNameMap.containsKey(1) && colorAndNameMap.containsKey(2)) {
            docType = section.get("doc13");
        }
        // 橙色预警和红色预警
        else if (!colorAndNameMap.containsKey(0) && colorAndNameMap.containsKey(1) && colorAndNameMap.containsKey(2)) {
            docType = section.get("doc12");
        }
        // 黄色预警和橙色预警和红色预警
        else if (colorAndNameMap.containsKey(1) && colorAndNameMap.containsKey(2) && colorAndNameMap.containsKey(0)) {
            docType = section.get("doc123");
        }
        // 无风险区
        else {
            docType = section.get("doc4");
        }
        //一级区县内容
        StringBuilder country1 = new StringBuilder();
        //二级区县内容
        StringBuilder country2 = new StringBuilder();
        //三级区县内容
        StringBuilder country3 = new StringBuilder();

        List<ColorAndNameDto> colorAndNameDtoListAll = new ArrayList<>();
        if (colorAndNameMap.containsKey(0)) {
            List<ColorAndNameDto> colorAndNameDtoList = colorAndNameMap.get(0);
            colorAndNameDtoListAll.addAll(colorAndNameDtoList);
            for (ColorAndNameDto colorAndNameDto : colorAndNameDtoList) {
                country1.append(colorAndNameDto.getCountry()).append(",");
            }
            country1.deleteCharAt(country1.length() - 1);

        }
        if (colorAndNameMap.containsKey(1)) {
            List<ColorAndNameDto> colorAndNameDtoList = colorAndNameMap.get(1);
            colorAndNameDtoListAll.addAll(colorAndNameDtoList);
            for (ColorAndNameDto colorAndNameDto : colorAndNameDtoList) {
                country2.append(colorAndNameDto.getCountry()).append(",");
            }
            country2.deleteCharAt(country2.length() - 1);

        }
        if (colorAndNameMap.containsKey(2)) {
            List<ColorAndNameDto> colorAndNameDtoList = colorAndNameMap.get(2);
            colorAndNameDtoListAll.addAll(colorAndNameDtoList);
            for (ColorAndNameDto colorAndNameDto : colorAndNameDtoList) {
                country3.append(colorAndNameDto.getCountry()).append(",");
            }
            country3.deleteCharAt(country3.length() - 1);
        }
        //替换正文内容
        String cityName = zdda01aService.queryCityName(userName);
        docType = docType.replace("[行政]", cityName);

        docType = docType.replace("[三级区县]", country1.toString());
        docType = docType.replace("[二级区县]", country2.toString());
        docType = docType.replace("[一级区县]", country3.toString());

        docType = docType.replace("[发布时间]", sdf1.format(new Date()));
        docType = docType.replace("[批号]", String.valueOf(issueNum));
        docType = docType.replace("[预警起报点]", sdf3.format(date1) + timeChar + "时");
        docType = docType.replace("[预警时长]", String.valueOf(nTimes));
        docType = docType.replace("[预警时效]", sdf3.format(date1) + timeChar + "时起" + nTimes + "小时");
        //设置点集合区县内容
        DzWarning dzWarning = new DzWarning();
        dzWarning.setPos(posStr);
        dzWarning.setGradearea3(country1.toString());
        dzWarning.setGradearea4(country2.toString());
        dzWarning.setGradearea5(country3.toString());
        //解析地理分析数据
        List<Object> layerObjectList = new ArrayList<>();
        if (StringUtils.isNotBlank(dlData) && StringUtils.isNotBlank(layerName)) {
            try {
                List<LayerRcoDto> LayerRcoDtoList = JSON.parseArray(dlData, LayerRcoDto.class);
                Class layerClass = LayerUtil.getLayerClass(layerName);
                for (LayerRcoDto layerRcoDto : LayerRcoDtoList) {
                    JSONObject rcoValObject = (JSONObject) layerRcoDto.getRcoValObject();
                    Object javaObject = JSON.toJavaObject(rcoValObject, layerClass);
                    layerObjectList.add(javaObject);
                }
            } catch (Exception e) {
                System.err.println("地理分析数据解析错误");
            }
        }

        //生成文档
        try (
                InputStream templateInputStream = new FileInputStream(templatePath);
                OutputStream targetOutputStream = new FileOutputStream(targetPath);
                XWPFDocument document = new XWPFDocument(templateInputStream);
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ) {
            List<XWPFParagraph> paragraphs = document.getParagraphs();
            String[] placeholders = new String[]{
                    "[行政]",
                    "[年份]",
                    "[文件号]", "[时间1]", "[时间2]", "[预警情况1]", "[时间3]"};
            String[] replacements = new String[]{
                    cityName,
                    year,
                    String.valueOf(issueNum), sdf3.format(date1), sdf3.format(date1) + timeChar + "时", docType
                    , sdf3.format(date1)
            };

            for (int i = 0; i < paragraphs.size(); i++) {
                XWPFParagraph paragraph = paragraphs.get(i);
                String text = paragraph.getText();

                DocxUtil.replaceTextInParagraph(paragraph, placeholders, replacements);


                //插入图片
                if (StringUtils.isNotBlank(text) && text.contains("[图1]")) {
                    //获取下标
                    XmlCursor cursor = paragraph.getCTP().newCursor();
                    XWPFParagraph newPara = document.insertNewParagraph(cursor);
                    newPara.setAlignment(ParagraphAlignment.CENTER);//居中
                    XWPFRun newParaRun = newPara.createRun();

                    for (MultipartFile image : images) {
                        //插入图片
                        CTSectPr sectPr = document.getDocument().getBody().getSectPr();
                        CTPageSz pageSize = sectPr.getPgSz();
                        int pageWidth = pageSize.getW().intValue() / 27;
                        //以前高度除以25，现在高度除以50
                        int pageHeight = pageSize.getH().intValue() / 60;
                        newParaRun.addPicture(image.getInputStream(), XWPFDocument.PICTURE_TYPE_PNG, "kill.png,", Units.toEMU(pageWidth), Units.toEMU(pageHeight));
                        FileUtil.bytesToFile(image.getBytes(), targetImgPath);
                    }
                    document.removeBodyElement(document.getPosOfParagraph(paragraph));
                }
                //插入预警区表格
                if (StringUtils.isNotBlank(text) && text.contains("[表1]")) {
                    //获取下标
                    XmlCursor cursor = paragraph.getCTP().newCursor();

                    // 去重，保留最大风险
                    Map<String, ColorAndNameDto> minType = new TreeMap<>();
                    for (ColorAndNameDto obj : colorAndNameDtoListAll) {
                        ColorAndNameDto existing = minType.get(obj.getCountry());
                        if (existing == null || existing.getType() < obj.getType()) {
                            minType.put(obj.getCountry(), obj);
                        }
                    }
                    // 将map的值转换回List
                    List<ColorAndNameDto> uniqueList = new ArrayList<>(minType.values());


                    if (uniqueList.size() > 0) {

                        XWPFTable table = document.insertNewTbl(cursor);
                        //添加表头
                        XWPFTableRow row_0 = table.getRow(0);
                        row_0.getCell(0).setText("乡镇");
                        row_0.addNewTableCell().setText("村庄");
                        row_0.addNewTableCell().setText("预警等级");

                        uniqueList.forEach(country -> {
                            XWPFTableRow dataRow = table.createRow();
                            dataRow.getCell(0).setText(country.getCounty());
                            dataRow.getCell(1).setText(country.getCountry());
                            switch (country.getColor()) {
                                case "黄色":
                                    dataRow.getCell(2).setText("风险较大（黄色预警）");
                                    break;
                                case "橙色":
                                    dataRow.getCell(2).setText("风险大（橙色预警）");
                                    break;
                                case "红色":
                                    dataRow.getCell(2).setText("风险极大（红色预警）");
                                    break;
                            }
                        });
                        DocxUtil.setTableLocation(table, "center");
                        DocxUtil.setCellLocation(table, "CENTER", "center");

                    }
                    document.removeBodyElement(document.getPosOfParagraph(paragraph));
                }

                //插入地灾隐患点表格
                if (StringUtils.isNotBlank(text) && text.contains("灾害点")) {
                    //获取下标
                    XmlCursor cursor = paragraph.getCTP().newCursor();


                    List<DisasterTypeNumVo> list = zdda01aService.dzTable(point, userName);

                    if (list != null && list.size() > 0) {
                        XWPFTable table = document.insertNewTbl(cursor);
                        //添加表头
                        XWPFTableRow row_0 = table.getRow(0);
                        row_0.getCell(0).setText("乡镇");
                        row_0.addNewTableCell().setText("总数");
                        row_0.addNewTableCell().setText("滑坡");
                        row_0.addNewTableCell().setText("崩塌");
                        row_0.addNewTableCell().setText("泥石流");
                        for (DisasterTypeNumVo disaster : list) {
                            XWPFTableRow dataRow = table.createRow();
                            dataRow.getCell(0).setText(disaster.getTownName());
                            dataRow.getCell(0).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
                            dataRow.getCell(1).setText(disaster.getSum().toString());
                            dataRow.getCell(2).setText(disaster.getHp().toString());
                            dataRow.getCell(3).setText(disaster.getBt().toString());
                            dataRow.getCell(4).setText(disaster.getNsl().toString());
                        }
                        DocxUtil.setTableLocation(table, "center");
                        DocxUtil.setCellLocation(table, "CENTER", "center");
                    }

                    document.removeBodyElement(document.getPosOfParagraph(paragraph));
                }

                //插入地理分析数据表格
                if (layerObjectList.size() > 0 && StringUtils.isNotBlank(text) && text.contains("[预警信息表]")) {
                    //获取下标
                    XmlCursor cursor = paragraph.getCTP().newCursor();
                    XWPFTable table = document.insertNewTbl(cursor);
                    //插入图层表格数据
                    DocxUtil.insertTablaLayerData(layerName, layerObjectList, table);
                    DocxUtil.setTableLocation(table, "center");
                    DocxUtil.setCellLocation(table, "CENTER", "center");
                    document.removeBodyElement(document.getPosOfParagraph(paragraph));

                }
            }
            // 将生成的文档保存到输出文件
            document.write(targetOutputStream);

            // 创建时间
            Date datetime = new Date();
            // 将时间转为 LocalDateTime
            LocalDateTime localDateTime = datetime.toInstant().atOffset(ZoneOffset.ofHours(8)).toLocalDateTime();
            Ybba02c ybba02c = new Ybba02c();
            ybba02c.setYbba02c010(new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(new Date()));//获取时分秒当id
            ybba02c.setYbba02c020(productName);
            ybba02c.setYbba02c030(localDateTime);
            ybba02c.setYbba02c040("");
            ybba02c.setYbba02c050(ling);
            ybba02c.setYbba02c060(ys);
            ybba02c.setYbba02c070(xz);
            ybba02c.setYbba02c080(colorAndPos.getBytes());
            ybba02c.setYbba02c090(userName);
            ybba02c.setYbba02c100(qx);
            ybba02c.setYbba02c110("");
            ybba02c.setYbba02c120(type1);
            ybba02cMapper.insert(ybba02c);

            byte[] buffer = new byte[1024];
            int bytesRead;
            FileInputStream inputStream = new FileInputStream(targetPath);
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, bytesRead);
            }
            byte[] byteArray = byteArrayOutputStream.toByteArray();
            File targetfile = new File(targetPath);
            //设置可执行权限
            boolean exec = targetfile.setExecutable(true, false);
            //设置可读权限
            boolean read = targetfile.setReadable(true, false);
            //设置可写权限
            boolean write = targetfile.setWritable(true, false);

            // 设置前端响应
            HttpHeaders headers = new HttpHeaders();
            headers.setContentDispositionFormData("attachment", productName + ".docx");
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentLength(byteArray.length);

            return new ResponseEntity<>(byteArray, headers, HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("文档生成失败");
        }
        return null;
    }


}
